More fixes for #77807:
authorMatthias Clasen <matthiasc@src.gnome.org>
Thu, 11 Apr 2002 21:18:40 +0000 (21:18 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Thu, 11 Apr 2002 21:18:40 +0000 (21:18 +0000)
* io-tga.c (get_contiguous_pixbuf): Helper function to create
a pixbuf with a contiguous pixel array while being careful about
overflow.

* io-tga.c (fill_in_context, get_image_pseudocolor,
get_image_truecolor, get_image_grayscale): Use
get_contiguous_pixbuf instead of manually allocating image
storage.

* io-xpm.c (pixbuf_create_from_xpm):
* io-pnm.c (gdk_pixbuf__pnm_image_load):
* io-jpeg.c (gdk_pixbuf__jpeg_image_load): Use gdk_pixbuf_new
instead of manually allocating image storage.

gdk-pixbuf/ChangeLog
gdk-pixbuf/io-jpeg.c
gdk-pixbuf/io-pnm.c
gdk-pixbuf/io-tga.c
gdk-pixbuf/io-xpm.c

index 6cde6b198a3f250eab1e9d584403d4353d8adc08..787589267a0c07ca229a7a8e444cd41d6dfa9810 100644 (file)
@@ -1,3 +1,21 @@
+2002-04-11  Matthias Clasen  <maclas@gmx.de>
+
+       More fixes for #77807:
+       
+       * io-tga.c (get_contiguous_pixbuf): Helper function to create
+       a pixbuf with a contiguous pixel array while being careful about
+       overflow. 
+
+       * io-tga.c (fill_in_context, get_image_pseudocolor,
+       get_image_truecolor, get_image_grayscale): Use 
+       get_contiguous_pixbuf instead of manually allocating image
+       storage. 
+
+       * io-xpm.c (pixbuf_create_from_xpm): 
+       * io-pnm.c (gdk_pixbuf__pnm_image_load):
+       * io-jpeg.c (gdk_pixbuf__jpeg_image_load): Use gdk_pixbuf_new
+       instead of manually allocating image storage.
+
 2002-04-09  Matthias Clasen  <maclas@gmx.de>
 
        * gdk-pixbuf-loader.c (gdk_pixbuf_loader_load_module): Use 
index 87bfbe185c45afe12cd026253b7b6eedd0634e2d..a2b3b7769529b77413256c0fd6dc4396c495ab9b 100644 (file)
@@ -58,7 +58,7 @@
 \f
 
 /* we are a "source manager" as far as libjpeg is concerned */
-#define JPEG_PROG_BUF_SIZE 4096
+#define JPEG_PROG_BUF_SIZE 65536
 
 typedef struct {
        struct jpeg_source_mgr pub;   /* public fields */
@@ -89,6 +89,7 @@ typedef struct {
        gboolean                 did_prescan;  /* are we in image data yet? */
        gboolean                 got_header;  /* have we loaded jpeg header? */
        gboolean                 src_initialized;/* TRUE when jpeg lib initialized */
+       gboolean                 in_output;   /* did we get suspended in an output pass? */
        struct jpeg_decompress_struct cinfo;
        struct error_handler_data     jerr;
 } JpegProgContext;
@@ -139,14 +140,6 @@ output_message_handler (j_common_ptr cinfo)
   /* do nothing */
 }
 
-/* Destroy notification function for the pixbuf */
-static void
-free_buffer (guchar *pixels, gpointer data)
-{
-       g_free (pixels);
-}
-
-
 /* explode gray image data from jpeg library into rgb components in pixbuf */
 static void
 explode_gray_into_buf (struct jpeg_decompress_struct *cinfo,
@@ -177,12 +170,76 @@ explode_gray_into_buf (struct jpeg_decompress_struct *cinfo,
        }
 }
 
+typedef struct {
+  struct jpeg_source_mgr pub;  /* public fields */
+
+  FILE * infile;               /* source stream */
+  JOCTET * buffer;             /* start of buffer */
+  boolean start_of_file;       /* have we gotten any data yet? */
+} stdio_source_mgr;
+
+typedef stdio_source_mgr * stdio_src_ptr;
+
+static void
+stdio_init_source (j_decompress_ptr cinfo)
+{
+  stdio_src_ptr src = (stdio_src_ptr)cinfo->src;
+  src->start_of_file = FALSE;
+}
+
+static boolean
+stdio_fill_input_buffer (j_decompress_ptr cinfo)
+{
+  stdio_src_ptr src = (stdio_src_ptr) cinfo->src;
+  size_t nbytes;
+
+  nbytes = fread (src->buffer, 1, JPEG_PROG_BUF_SIZE, src->infile);
+
+  if (nbytes <= 0) {
+#if 0
+    if (src->start_of_file)    /* Treat empty input file as fatal error */
+      ERREXIT(cinfo, JERR_INPUT_EMPTY);
+    WARNMS(cinfo, JWRN_JPEG_EOF);
+#endif
+    /* Insert a fake EOI marker */
+    src->buffer[0] = (JOCTET) 0xFF;
+    src->buffer[1] = (JOCTET) JPEG_EOI;
+    nbytes = 2;
+  }
+
+  src->pub.next_input_byte = src->buffer;
+  src->pub.bytes_in_buffer = nbytes;
+  src->start_of_file = FALSE;
+
+  return TRUE;
+}
+
+static void
+stdio_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+  stdio_src_ptr src = (stdio_src_ptr) cinfo->src;
+
+  if (num_bytes > 0) {
+    while (num_bytes > (long) src->pub.bytes_in_buffer) {
+      num_bytes -= (long) src->pub.bytes_in_buffer;
+      (void)stdio_fill_input_buffer(cinfo);
+    }
+    src->pub.next_input_byte += (size_t) num_bytes;
+    src->pub.bytes_in_buffer -= (size_t) num_bytes;
+  }
+}
+
+static void
+stdio_term_source (j_decompress_ptr cinfo)
+{
+}
+
 /* Shared library entry point */
 static GdkPixbuf *
 gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
 {
-       gint w, h, i;
-       guchar * volatile pixels = NULL;
+       gint i;
+       GdkPixbuf * volatile pixbuf = NULL;
        guchar *dptr;
        guchar *lines[4]; /* Used to expand rows, via rec_outbuf_height, 
                            * from the header file: 
@@ -192,6 +249,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
        guchar **lptr;
        struct jpeg_decompress_struct cinfo;
        struct error_handler_data jerr;
+       stdio_src_ptr src;
 
        /* setup error handler */
        cinfo.err = jpeg_std_error (&jerr.pub);
@@ -202,8 +260,8 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
         
        if (sigsetjmp (jerr.setjmp_buffer, 1)) {
                /* Whoops there was a jpeg error */
-               if (pixels)
-                       g_free (pixels);
+               if (pixbuf)
+                       g_object_unref (pixbuf);
 
                jpeg_destroy_decompress (&cinfo);
                return NULL;
@@ -211,17 +269,32 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
 
        /* load header, setup */
        jpeg_create_decompress (&cinfo);
-       jpeg_stdio_src (&cinfo, f);
+
+       cinfo.src = (struct jpeg_source_mgr *)
+         (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
+                                 sizeof (stdio_source_mgr));
+       src = (stdio_src_ptr) cinfo.src;
+       src->buffer = (JOCTET *)
+         (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
+                                     JPEG_PROG_BUF_SIZE * sizeof (JOCTET));
+
+       src->pub.init_source = stdio_init_source;
+       src->pub.fill_input_buffer = stdio_fill_input_buffer;
+       src->pub.skip_input_data = stdio_skip_input_data;
+       src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+       src->pub.term_source = stdio_term_source;
+       src->infile = f;
+       src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+       src->pub.next_input_byte = NULL; /* until buffer loaded */
+
        jpeg_read_header (&cinfo, TRUE);
        jpeg_start_decompress (&cinfo);
        cinfo.do_fancy_upsampling = FALSE;
        cinfo.do_block_smoothing = FALSE;
 
-       w = cinfo.output_width;
-       h = cinfo.output_height;
-
-       pixels = g_try_malloc (h * w * 3);
-       if (!pixels) {
+       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, cinfo.output_width, cinfo.output_height);
+       if (!pixbuf) {
                jpeg_destroy_decompress (&cinfo);
 
                 /* broken check for *error == NULL for robustness against
@@ -237,7 +310,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
                return NULL;
        }
 
-       dptr = pixels;
+       dptr = pixbuf->pixels;
 
        /* decompress all the lines, a few at a time */
 
@@ -245,7 +318,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
                lptr = lines;
                for (i = 0; i < cinfo.rec_outbuf_height; i++) {
                        *lptr++ = dptr;
-                       dptr += w * 3;
+                       dptr += pixbuf->rowstride;
                }
 
                jpeg_read_scanlines (&cinfo, lines, cinfo.rec_outbuf_height);
@@ -257,9 +330,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
        jpeg_finish_decompress (&cinfo);
        jpeg_destroy_decompress (&cinfo);
 
-       return gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, FALSE, 8,
-                                        w, h, w * 3,
-                                        free_buffer, NULL);
+       return pixbuf;
 }
 
 
@@ -333,6 +404,7 @@ gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func,
        context->got_header = FALSE;
        context->did_prescan = FALSE;
        context->src_initialized = FALSE;
+       context->in_output = FALSE;
 
        /* create libjpeg structures */
        jpeg_create_decompress (&context->cinfo);
@@ -483,9 +555,6 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data,
                        num_copy = MIN (JPEG_PROG_BUF_SIZE - src->pub.bytes_in_buffer,
                                        num_left);
 
-/*                     if (num_copy == 0) 
-                               g_error ("Buffer overflow!");
-*/
                        memcpy(src->buffer + src->pub.bytes_in_buffer, bufhd,num_copy);
                        src->pub.next_input_byte = src->buffer;
                        src->pub.bytes_in_buffer += num_copy;
@@ -518,13 +587,6 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data,
 
                        context->got_header = TRUE;
 
-#if 0
-                       if (jpeg_has_multiple_scans (cinfo)) {
-                               g_print ("io-jpeg.c: Does not currently "
-                                        "support progressive jpeg files.\n");
-                               return FALSE;
-                       }
-#endif
                        context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 
                                                         FALSE,
                                                         8, 
@@ -549,75 +611,70 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data,
 
                } else if (!context->did_prescan) {
                        int rc;
-
+                       
                        /* start decompression */
+                       cinfo->buffered_image = TRUE;
                        rc = jpeg_start_decompress (cinfo);
                        cinfo->do_fancy_upsampling = FALSE;
                        cinfo->do_block_smoothing = FALSE;
-
+                       
                        if (rc == JPEG_SUSPENDED)
                                continue;
 
                        context->did_prescan = TRUE;
                } else {
-
                        /* we're decompressing so feed jpeg lib scanlines */
                        guchar *lines[4];
                        guchar **lptr;
                        guchar *rowptr;
                        gint   nlines, i;
-                       gint   start_scanline;
-
-                       /* keep going until we've done all scanlines */
-                       while (cinfo->output_scanline < cinfo->output_height) {
-                               start_scanline = cinfo->output_scanline;
-                               lptr = lines;
-                               rowptr = context->dptr;
-                               for (i=0; i < cinfo->rec_outbuf_height; i++) {
-                                       *lptr++ = rowptr;
-                                       rowptr += context->pixbuf->rowstride;
-                               }
 
-                               nlines = jpeg_read_scanlines (cinfo, lines,
-                                                             cinfo->rec_outbuf_height);
-                               if (nlines == 0)
+                       /* keep going until we've done all passes */
+                       while (!jpeg_input_complete (cinfo)) {
+                               if (!context->in_output) {
+                                       if (jpeg_start_output (cinfo, cinfo->input_scan_number)) {
+                                               context->in_output = TRUE;
+                                               context->dptr = context->pixbuf->pixels;
+                                       }
+                                       else
+                                               break;
+                               }
+                               /* keep going until we've done all scanlines */
+                               while (cinfo->output_scanline < cinfo->output_height) {
+                                       lptr = lines;
+                                       rowptr = context->dptr;
+                                       for (i=0; i < cinfo->rec_outbuf_height; i++) {
+                                               *lptr++ = rowptr;
+                                               rowptr += context->pixbuf->rowstride;
+                                       }
+                                       
+                                       nlines = jpeg_read_scanlines (cinfo, lines,
+                                                                     cinfo->rec_outbuf_height);
+                                       if (nlines == 0)
+                                               break;
+
+                                       /* handle gray */
+                                       if (cinfo->output_components == 1)
+                                               explode_gray_into_buf (cinfo, lines);
+                                       
+                                       context->dptr += nlines * context->pixbuf->rowstride;
+                                       
+                                       /* send updated signal */
+                                       (* context->updated_func) (context->pixbuf,
+                                                                  0, 
+                                                                  cinfo->output_scanline-1,
+                                                                  cinfo->image_width, 
+                                                                  nlines,
+                                                                  context->user_data);
+                               }
+                               if (cinfo->output_scanline >= cinfo->output_height && 
+                                   jpeg_finish_output (cinfo))
+                                       context->in_output = FALSE;
+                               else
                                        break;
-
-                               /* handle gray */
-                               if (cinfo->output_components == 1)
-                                       explode_gray_into_buf (cinfo, lines);
-
-                               context->dptr += nlines * context->pixbuf->rowstride;
-
-                               /* send updated signal */
-                               (* context->updated_func) (context->pixbuf,
-                                                          0, 
-                                                          cinfo->output_scanline-1,
-                                                          cinfo->image_width, 
-                                                          nlines,
-                                                          context->user_data);
-
-#undef DEBUG_JPEG_PROGRESSIVE
-#ifdef DEBUG_JPEG_PROGRESSIVE
-                               
-                               if (start_scanline != cinfo->output_scanline)
-                                       g_print("jpeg: Input pass=%2d, next input scanline=%3d,"
-                                               " emitted %3d - %3d\n",
-                                               cinfo->input_scan_number, cinfo->input_iMCU_row * 16,
-                                               start_scanline, cinfo->output_scanline - 1);
-                               
-                               
-                               
-                               g_print ("Scanline %d of %d - ", 
-                                        cinfo->output_scanline,
-                                        cinfo->output_height);
-/*                     g_print ("rec_height %d -", cinfo->rec_outbuf_height); */
-                               g_print ("Processed %d lines - bytes left = %d\n",
-                                        nlines, cinfo->src->bytes_in_buffer);
-#endif
                        }
-                       /* did entire image */
-                       if (cinfo->output_scanline >= cinfo->output_height)
+                       if (jpeg_input_complete (cinfo))
+                               /* did entire image */
                                return TRUE;
                        else
                                continue;
@@ -642,7 +699,7 @@ gdk_pixbuf__jpeg_image_save (FILE          *f,
        guchar *pixels = NULL;
        JSAMPROW *jbuf;
        int y = 0;
-       int quality = 75; /* default; must be between 0 and 100 */
+       volatile int quality = 75; /* default; must be between 0 and 100 */
        int i, j;
        int w, h = 0;
        int rowstride = 0;
index adf843f33cbe148a7ace3ac74be17ccc0bd06c5d..797f9371782e5d101098ca8386936b526e3e2ffc 100644 (file)
@@ -93,13 +93,6 @@ static gboolean    gdk_pixbuf__pnm_image_load_increment (gpointer context,
 static void explode_bitmap_into_buf              (PnmLoaderContext *context);
 static void explode_gray_into_buf                (PnmLoaderContext *context);
 
-/* Destroy notification function for the pixbuf */
-static void
-free_buffer (guchar *pixels, gpointer data)
-{
-       g_free (pixels);
-}
-
 
 /* explode bitmap data into rgb components         */
 /* we need to know what the row so we can          */
@@ -764,10 +757,10 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error)
                        context.output_row = 0;
                        context.output_col = 0;
                        
-                       context.rowstride = context.width * 3;
-                       context.pixels = g_try_malloc (context.height * context.width * 3);
+                       context.pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+                                                        context.width, context.height);
                        
-                       if (!context.pixels) {
+                       if (!context.pixbuf) {
                                /* Failed to allocate memory */
                                g_set_error (error,
                                             GDK_PIXBUF_ERROR,
@@ -775,6 +768,9 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error)
                                             _("Can't allocate memory for loading PNM image"));
                                return NULL;
                        }
+
+                       context.rowstride = context.pixbuf->rowstride;
+                       context.pixels = context.pixbuf->pixels;
                }
                
                /* if we got here we're reading image data */
@@ -797,10 +793,7 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error)
                        break;
        }
        
-       return gdk_pixbuf_new_from_data (context.pixels, GDK_COLORSPACE_RGB, FALSE, 8,
-                                        context.width, context.height, 
-                                        context.width * 3, free_buffer, NULL);
-
+       return context.pixbuf;
 }
 
 /* 
index 69c55faa8ffdcaaa58ff6de788360e3e40b8dd21..87a7ea659ad4b259ce22b0461cd90a8407eea940 100644 (file)
@@ -242,6 +242,37 @@ static void free_buffer(guchar *pixels, gpointer data)
        g_free(pixels);
 }
 
+static GdkPixbuf *get_contiguous_pixbuf (guint width, 
+                                        guint height, 
+                                        gboolean has_alpha)
+{
+       guchar *pixels;
+       guint channels, rowstride, bytes;
+       
+       if (has_alpha) 
+               channels = 4;
+       else 
+               channels = 3;
+       
+       rowstride = width * channels;
+       
+       if (rowstride / channels != width)
+                return NULL;                
+
+       bytes = height * rowstride;
+
+        if (bytes / rowstride != height)
+                return NULL;                
+
+        pixels = g_try_malloc (bytes);
+
+       if (!pixels)
+               return NULL;
+       
+       return gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, has_alpha, 8,
+                                        width, height, rowstride, free_buffer, NULL);
+}
+
 static gboolean fread_check(gpointer dest, 
                            size_t size, size_t count, 
                            FILE *f, GError **err)
@@ -268,7 +299,6 @@ static gboolean fill_in_context(TGAContext *ctx, GError **err)
 {
        gboolean alpha;
        guint w, h;
-       guchar *pixels;
 
        g_return_val_if_fail(ctx != NULL, FALSE);
 
@@ -288,23 +318,14 @@ static gboolean fill_in_context(TGAContext *ctx, GError **err)
        w = LE16(ctx->hdr->width);
        h = LE16(ctx->hdr->height);
 
-       pixels = g_try_malloc (w * h * (alpha ? 4 : 3));
-
-       if (!pixels) {
-               g_set_error(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                           _("Insufficient memory to load TGA image"));
-               return FALSE;
-       }       
-       
-       ctx->pbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, alpha, 8,
-                                             w, h, w * (alpha ? 4 : 3),
-                                             free_buffer, NULL);
+       ctx->pbuf = get_contiguous_pixbuf (w, h, alpha);
 
        if (!ctx->pbuf) {
                g_set_error(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                            _("Can't allocate new pixbuf"));
                return FALSE;
        }
+
        ctx->pbuf_bytes = ctx->pbuf->rowstride * ctx->pbuf->height;
        ctx->pptr = ctx->pbuf->pixels;
 
@@ -1000,7 +1021,6 @@ static GdkPixbuf *get_image_pseudocolor(FILE *f, TGAHeader *hdr,
        guchar *p, color, tag;
        glong n, image_offset;
        guint count, w, h;
-       guchar *pixels;
        gboolean alpha;
 
        image_offset = sizeof(TGAHeader) + hdr->infolen;
@@ -1023,17 +1043,8 @@ static GdkPixbuf *get_image_pseudocolor(FILE *f, TGAHeader *hdr,
 
        alpha = (hdr->cmap_bpp == 32);
 
-       pixels = g_try_malloc (w * h * (alpha ? 4 : 3));
+       pbuf = get_contiguous_pixbuf (w, h, alpha);
 
-       if (!pixels) {
-               g_set_error(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                           _("Insufficient memory to load TGA image"));
-               return FALSE;
-       }       
-       
-       pbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, alpha, 8,
-                                        w, h, w * (alpha ? 4 : 3),
-                                        free_buffer, NULL);
        if (!pbuf) {
                g_set_error(err, GDK_PIXBUF_ERROR, 
                            GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
@@ -1120,7 +1131,6 @@ static GdkPixbuf *get_image_truecolor(FILE *f, TGAHeader *hdr,
        glong n, image_offset;
        guint32 pixel;
        guint count, w, h;
-       guchar *pixels;
        gboolean alpha;
 
        image_offset = sizeof(TGAHeader) + hdr->infolen;
@@ -1135,17 +1145,7 @@ static GdkPixbuf *get_image_truecolor(FILE *f, TGAHeader *hdr,
        
        alpha = (hdr->bpp == 32);
 
-       pixels = g_try_malloc (w * h * (alpha ? 4 : 3));
-
-       if (!pixels) {
-               g_set_error(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                           _("Insufficient memory to load TGA image"));
-               return FALSE;
-       }       
-       
-       pbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, alpha, 8,
-                                        w, h, w * (alpha ? 4 : 3),
-                                        free_buffer, NULL);
+       pbuf = get_contiguous_pixbuf (w, h, alpha);
 
        if (!pbuf) {
                g_set_error(err, GDK_PIXBUF_ERROR, 
@@ -1153,8 +1153,6 @@ static GdkPixbuf *get_image_truecolor(FILE *f, TGAHeader *hdr,
                            _("Can't allocate pixbuf"));
                return NULL;
        }
-       pbuf->destroy_fn = free_buffer;
-       pbuf->destroy_fn_data = NULL;
        p = pbuf->pixels;
 
        if (rle) {
@@ -1203,7 +1201,6 @@ static GdkPixbuf *get_image_grayscale(FILE *f, TGAHeader *hdr,
        glong n, image_offset;
        guchar *p, color[2], tag;
        guint count, w, h;
-       guchar *pixels;
        gboolean alpha;
 
        image_offset = sizeof(TGAHeader) + hdr->infolen;
@@ -1218,26 +1215,14 @@ static GdkPixbuf *get_image_grayscale(FILE *f, TGAHeader *hdr,
 
        alpha = (hdr->bpp == 16);
 
-       pixels = g_try_malloc (w * h * (alpha ? 4 : 3));
-
-       if (!pixels) {
-               g_set_error(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                           _("Insufficient memory to load TGA image"));
-               return FALSE;
-       }       
+       pbuf = get_contiguous_pixbuf (w, h, alpha);
        
-       pbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, alpha, 8,
-                                        w, h, w * (alpha ? 4 : 3),
-                                        free_buffer, NULL);
-
        if (!pbuf) {
                g_set_error(err, GDK_PIXBUF_ERROR, 
                            GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                            _("Can't allocate pixbuf"));
                return NULL;
        }
-       pbuf->destroy_fn = free_buffer;
-       pbuf->destroy_fn_data = NULL;
        p = pbuf->pixels;
 
        if (rle) {
index 2e6e33aae404842e95d558c98bc551bbaacd87d9..3f047298962677cad263ac5d0b619d02d82f2e52 100644 (file)
@@ -1203,13 +1203,6 @@ mem_buffer (enum buf_op op, gpointer handle)
        return NULL;
 }
 
-/* Destroy notification function for the pixbuf */
-static void
-free_buffer (guchar *pixels, gpointer data)
-{
-       g_free (pixels);
-}
-
 /* This function does all the work. */
 static GdkPixbuf *
 pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handle), gpointer handle,
@@ -1223,7 +1216,8 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl
        gchar pixel_str[32];
        GHashTable *color_hash;
        XPMColor *colors, *color, *fallbackcolor;
-       guchar *pixels, *pixtmp;
+       guchar *pixtmp;
+       GdkPixbuf *pixbuf;
 
        fallbackcolor = NULL;
 
@@ -1314,12 +1308,9 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl
                        fallbackcolor = color;
        }
 
-       if (is_trans)
-               pixels = g_try_malloc (w * h * 4);
-       else
-               pixels = g_try_malloc (w * h * 3);
+       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, is_trans, 8, w, h);
 
-       if (!pixels) {
+       if (!pixbuf) {
                 g_set_error (error,
                              GDK_PIXBUF_ERROR,
                              GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
@@ -1331,7 +1322,7 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl
        }
 
        wbytes = w * cpp;
-       pixtmp = pixels;
+       pixtmp = pixbuf->pixels;
 
        for (ycnt = 0; ycnt < h; ycnt++) {
                buffer = (*get_buf) (op_body, handle);
@@ -1364,9 +1355,7 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl
        g_free (colors);
        g_free (name_buf);
 
-       return gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, is_trans, 8,
-                                        w, h, is_trans ? (w * 4) : (w * 3),
-                                        free_buffer, NULL);
+       return pixbuf;
 }
 
 /* Shared library entry point for file loading */